#include <GLTools.h>            // OpenGL  toolkit
#include <glFrame.h>
#include <glFrustum.h> 
#include <StopWatch.h> 

#ifdef __APPLE__
#include <glut/glut.h>          // OS X version of GLUT
#else
#include <gl/glut.h>            // Windows FreeGlut equivalent
#endif
#define M_PI       3.14159265358979323846
GLuint shader;
void renderPodstawa();
void renderBoki();
static GLint MVPMatrixLocation;

GLFrustum viewFrustum;
GLFrame cameraFrame;
CStopWatch timer;

void SetUpFrame(GLFrame &frame,const M3DVector3f origin,const M3DVector3f forward,const M3DVector3f up) {
	frame.SetOrigin(origin);
	frame.SetForwardVector(forward);
	M3DVector3f side,oUp;
	m3dCrossProduct3(side,forward,up);
	m3dCrossProduct3(oUp,side,forward);
	frame.SetUpVector(oUp);
	frame.Normalize();
};
void LookAt(GLFrame &frame, const M3DVector3f eye, const M3DVector3f at, const M3DVector3f up) {
	M3DVector3f forward;
	m3dSubtractVectors3(forward, at, eye);
	SetUpFrame(frame, eye, forward, up);
}
void ChangeSize(int w, int h) {
	glViewport(0, 0, w, h);
	viewFrustum.SetPerspective(45.0f, w / h, 0.1f, 100.0f);
}

void SetupRC() {
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	shader = gltLoadShaderPairWithAttributes("cw2_thru_shader.vp", "cw2_thru_shader.fp",
		2, GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_COLOR, "vColor");
	fprintf(stdout, "GLT_ATTRIBUTE_VERTEX : %d\nGLT_ATTRIBUTE_COLOR : %d \n",
		GLT_ATTRIBUTE_VERTEX, GLT_ATTRIBUTE_COLOR);
	MVPMatrixLocation=glGetUniformLocation(shader,"MVPMatrix");
	if(MVPMatrixLocation==-1)
	{
		fprintf(stderr,"uniform MVPMatrix could not be found\n");
	}
}

void RenderScene(void) {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);
	glFrontFace(GL_CCW); 
	glUseProgram(shader);
	M3DVector3f at={0,0,0};
	M3DVector3f up={0,0,1};
	M3DVector3f eye;
	float angle =timer.GetElapsedSeconds()*M_PI;
	eye[0]=6.8f*cos(angle);
	eye[1]=6.0f*sin(angle);
	eye[2]=5.0f; 
	LookAt(cameraFrame,eye,at,up);
	M3DMatrix44f CameraMatrix;
	M3DMatrix44f ViewProjectionMatrix;
	M3DMatrix44f mCamera;
	cameraFrame.GetCameraMatrix(mCamera);
	m3dMatrixMultiply44(ViewProjectionMatrix,viewFrustum.GetProjectionMatrix(),mCamera);
	glUniformMatrix4fv(MVPMatrixLocation,1,GL_FALSE,ViewProjectionMatrix);
	renderPodstawa();
	renderBoki();
	glutSwapBuffers();
	glutPostRedisplay();
}


void renderPodstawa(){
	glBegin(GL_QUADS);
	glVertexAttrib3f(GLT_ATTRIBUTE_COLOR, 0.84, 0.84, 0.84);
	glVertex3f(-1.0f,1.0f,0.0f);
	glVertex3f(1.0f,1.0f,0.0f);
	glVertex3f(1.0f,-1.0f,0.0f);
	glVertex3f(-1.0f,-1.0f,0.0f);
	glEnd();
}
void renderBoki(){
	float z = 2.0f;
	glBegin(GL_TRIANGLES);
	glVertexAttrib3f(GLT_ATTRIBUTE_COLOR, 0.0, 0.0, 1.0);
	glVertex3f(-1.0f, 1.0f, 0.0f);
	glVertex3f(-1.0f, -1.0f, 0.0f);
	glVertex3f(0.0f, 0.0f, z);
	glVertexAttrib3f(GLT_ATTRIBUTE_COLOR, 0.0, 1.0, 0.0);
	glVertex3f(0.0f, 0.0f, z);
	glVertex3f(-1.0f, -1.0f, 0.0f);
	glVertex3f(1.0f, -1.0f, 0.0f);
	glVertexAttrib3f(GLT_ATTRIBUTE_COLOR, 1.0, 0.0, 0.0);
	glVertex3f(1.0f, -1.0f, 0.0f);
	glVertex3f(1.0f, 1.0f, 0.0f);
	glVertex3f(0.0f, 0.0f, z);
	glVertexAttrib3f(GLT_ATTRIBUTE_COLOR, 1.0, 1.0, 0.0);
	glVertex3f(0.0f, 0.0f, z);
	glVertex3f(1.0f, 1.0f, 0.0f);
	glVertex3f(-1.0f, 1.0f, 0.0f);
	glEnd();
}

int main(int argc, char* argv[]) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
	glutInitWindowSize(800, 600);
	glutCreateWindow("Zadanie 2");
	glutReshapeFunc(ChangeSize);
	glutDisplayFunc(RenderScene);
	GLenum err = glewInit();
	if (GLEW_OK != err) {
		fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
		return 1;
	}
	SetupRC();
	glutMainLoop();
	return 0;
}